#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "Base64.cpp"
#include "RSA1.cpp"
#define PORT 3490
#define BACKLOG 10
#define MAXDATASIZE 1000
using namespace std;
class Sender{
public:
	Sender(const string &h);
	void negotiate(const string &_message);
	string receiveMsg();
	void sendMsg(const string s);
private:
	string host;
	int sockfd;
	int numbytes;
	struct hostent *he;
	struct sockaddr_in their_addr;
	void connect_receiver();
	void initialize();
};
Sender:: Sender(const string &h):host(h){
	this->initialize();
}
void Sender::connect_receiver(){
	if(connect(sockfd,(struct sockaddr *)&their_addr,sizeof(struct sockaddr))==-1){
		perror("connect error");
		exit(1);
	}
}
void Sender::initialize(){
	if((he=gethostbyname(host.c_str()))==NULL){
		herror("get host by name");
		exit(1);
	}
	if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1){
		perror("socket error");
		exit(1);
	}
	this->their_addr.sin_family=AF_INET;
	this->their_addr.sin_port=htons(PORT);
	this->their_addr.sin_addr=*((struct in_addr *)he->h_addr);
	bzero(&(their_addr.sin_zero),sizeof(their_addr.sin_zero));
	connect_receiver();

}
void  Sender::sendMsg(const string s){
	if(!fork()){
		if(send(sockfd,s.c_str(),s.size(),0)==-1)
			perror("send error");
		close(sockfd);
		exit(0);
	}
}

string Sender::receiveMsg(){
	char buf[MAXDATASIZE];
	if((numbytes=recv(sockfd,buf,MAXDATASIZE,0))==-1){
		perror("recv");
		exit(1);
	}
	buf[numbytes]='\0';
	string str(buf);
	return str;
}

void Sender::negotiate(const string &_message){
	string message=_message;
	string output="";
	ofstream fout("key.txt");
	int n,e,d;
	RSA_Initialize(n,e,d);
	fout<<d<<" "<<n;
	fout.close();
	char * enc_output=Base64Encode(message.c_str(), message.length(), true);
	string str=enc_output;
	RSA_Encrypt(e,n,str,output);
	sendMsg(output);
}
/**
int main()
{
	Sender sender("127.0.0.1");
	//cout<<sender.receiveMsg();
	sender.sendMsg("negotiation");
	if(sender.receiveMsg()=="OK"){
		sender.negotiate("hello AES_MD5_7");
	}
	cout<<sender.receiveMsg()<<endl;;
	return 0;
}**/